using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using SubSonic.SqlGeneration.Schema;
using Webbness.Mvc.Security;
using Webbness.Mvc.SubSonic;
using Webbness.Mvc.Validators;

namespace Webbness.Mvc.Models
{
    public abstract class SecurityUser<TUser, TJoin, TRole> : Record
        where TUser : SecurityUser<TUser, TJoin, TRole>, new()
        where TRole : SecurityRole<TRole, TJoin, TUser>, new()
        where TJoin : SecurityUserInRole<TRole, TJoin, TUser>, new()
    {
        private List<TRole> _roles;
        private string cpassword;
        private string password;

        [SubSonicPrimaryKey]
        [HiddenInput]
        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public override int Id { get; set; }

        
        [DisplayName("User Name")]
        [Required]
        public virtual string UserName { get; set; }

        [DisplayName("Email Address")]
        [EmailValidator]
        public virtual string Email { get; set; }

        [DisplayName("Comment")]
        [SubSonicLongString]
        [DataType(DataType.MultilineText)]
        [SubSonicNullString]
        public virtual string Comment { get; set; }

        [DisplayName("Password")]
        [Required]
        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual string Password
        {
            get { return password; }
            set
            {
                password = value;
                cpassword = EncryptionHelper.DecryptPassword(value);
            }
        }

        [Required]
        [DataType(DataType.Text)]
        [DisplayName("Password")]
        [SubSonicIgnore]
        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual string ClearPassword
        {
            get { return cpassword; }
            set
            {
                cpassword = value;
                password = value == null ? null : EncryptionHelper.EncryptPassword(value);
            }
        }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        [SubSonicNullString]
        public virtual string PasswordQuestion { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        [SubSonicNullString]
        public virtual string PasswordAnswer { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual bool IsAnonymous { get; set; }

        public virtual bool IsApproved { get; set; }
        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime LastActivityDate { get; set; }
        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime LastLoginDate { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime LastPasswordChangedDate { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime CreationDate { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual bool IsOnLine { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual bool IsLockedOut { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime LastLockedOutDate { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual int FailedPasswordAttemptCount { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime? FailedPasswordAttemptWindowStart { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual int FailedPasswordAnswerAttemptCount { get; set; }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual DateTime? FailedPasswordAnswerAttemptWindowStart { get; set; }



        protected virtual List<TJoin> UserInRoles
        {
            get { return GetForeignList<TJoin>(m => m.UserID == Id); }
        }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual List<TRole> Roles
        {
            get
            {
                if (_roles == null)
                {
                    IQueryable<TRole> i = from r in Repository.Repo.All<TRole>() join uir in Repository.Repo.All<TJoin>() on r.Id equals uir.RoleID where (Id == uir.UserID) select r;
                    _roles = i.ToList();
                }
                return _roles;
            }
        }

        [ScaffoldColumn(false)]
        [ScaffoldInList(false)]
        public virtual List<CheckBoxItem> AllRoles
        {
            get
            {
                var lst = new List<CheckBoxItem>();

                foreach (var r in Repository.Repo.All<TRole>())
                {
                    var user = r.Users.SingleOrDefault(u => u.Id == Id);
                    CheckBoxItem cbi;
                    if (user == null)
                    {
                        cbi = new CheckBoxItem {RoleName = r.RoleName, Checked = false, RoleID = r.Id, UserID = Id};
                    }
                    else
                    {
                        cbi = new CheckBoxItem {RoleName = r.RoleName, Checked = true, RoleID = r.Id, UserID = Id};
                    }
                    lst.Add(cbi);
                }

                return lst;
            }
        }

        public override string ToString()
        {
            return UserName;
        }
    }

    public class CheckBoxItem
    {
        public int UserID { get; set; }
        public int RoleID { get; set; }
        public string RoleName { get; set; }
        public bool Checked { get; set; }
    }
}